import { EventManager, MyEvent } from "../Managers/EventManager";

const { ccclass, property } = cc._decorator;

@ccclass
export class Joystick extends cc.Component {
    private _joystickBase: cc.Node = null;
    private _joystickDot: cc.Node = null;
    private _attack: cc.Node = null;
    private _attackDot: cc.Node = null;
    private _movementTouch: cc.Event.EventTouch = null;
    private _attackMovementTouch: cc.Event.EventTouch = null;

    protected onLoad(): void {
        let joystickArea = this.node.getChildByName(`JoystickArea`);
        joystickArea.on(cc.Node.EventType.TOUCH_START, this.OnTouchStart, this);
        joystickArea.on(cc.Node.EventType.TOUCH_MOVE, this.OnTouchMove, this);
        joystickArea.on(cc.Node.EventType.TOUCH_END, this.OnTouchEnd, this);
        joystickArea.on(cc.Node.EventType.TOUCH_CANCEL, this.OnTouchEnd, this);

        this._joystickBase = this.node.getChildByName('JoystickBase');
        this._joystickDot = this._joystickBase.getChildByName('JoystickDot');

        this._attack = this.node.getChildByName(`Attack`);
        this._attackDot = this._attack.getChildByName(`AttackDot`);

        this._attack.on(cc.Node.EventType.TOUCH_START, this.OnAttackTouchStart, this);
        this._attack.on(cc.Node.EventType.TOUCH_MOVE, this.OnAttackTouchMove, this);
        this._attack.on(cc.Node.EventType.TOUCH_END, this.OnAttackTouchEnd, this);
        this._attack.on(cc.Node.EventType.TOUCH_CANCEL, this.OnAttackTouchEnd, this);

    }

    start() {
        cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, this.onKeyDown, this);
        cc.systemEvent.on(cc.SystemEvent.EventType.KEY_UP, this.onKeyUp, this);
    }

    onDestroy() { }

    OnTouchStart(event: cc.Event.EventTouch) {
        let touches = event.getTouches();
        for (let i = 0; i < touches.length; ++i) {
            let touch = touches[i];
            let x = touch.getLocationX();
            let y = touch.getLocationY();
            if (!this._movementTouch) {
                // this._joystickBase.setPosition(x - this.node.width / 2, y - this.node.height / 2, 0);
                this._joystickDot.setPosition(0, 0, 0);
                this._movementTouch = touch;
            }
        }
    }

    OnTouchMove(event: cc.Event.EventTouch) {
        let touches = event.getTouches();
        for (let i = 0; i < touches.length; ++i) {
            let touch = touches[i];
            if (this._movementTouch && touch.getID() == this._movementTouch.getID()) {
                let x = touch.getLocationX();
                let y = touch.getLocationY();

                let pos = this._joystickBase.position;
                let ox = x - this.node.width / 2 - pos.x;
                let oy = y - this.node.height / 2 - pos.y;

                let len = Math.sqrt(ox * ox + oy * oy);
                if (len <= 0) {
                    return;
                }

                let dirX = ox / len;
                let dirY = oy / len;
                let radius = this._joystickBase.width / 2;
                if (len > radius) {
                    len = radius;
                    ox = dirX * radius;
                    oy = dirY * radius;
                }

                this._joystickDot.setPosition(ox, oy, 0);

                // // degree 0 ~ 360 based on x axis.
                // let degree = Math.atan(dirY / dirX) / Math.PI * 180;
                // if (dirX < 0) {
                //     degree += 180;
                // }
                // else {
                //     degree += 360;
                // }

                EventManager.Scene.emit(MyEvent.MOVEMENT, dirX, dirY, len / radius);
            }
        }
    }

    OnTouchEnd(event: cc.Event.EventTouch) {
        let touches = event.getTouches();
        for (let i = 0; i < touches.length; ++i) {
            let touch = touches[i];
            if (this._movementTouch && touch.getID() == this._movementTouch.getID()) {
                EventManager.Scene.emit(MyEvent.MOVEMENT_STOP);
                this._movementTouch = null;
                this._joystickDot.setPosition(cc.Vec3.ZERO);
            }
        }
    }

    OnAttackTouchStart(event: cc.Event.EventTouch) {
        let touches = event.getTouches();
        EventManager.Scene.emit(MyEvent.Fire);

        for (let i = 0; i < touches.length; ++i) {
            let touch = touches[i];
            let x = touch.getLocationX();
            let y = touch.getLocationY();
            if (!this._attackMovementTouch) {
                // this._joystickBase.setPosition(x - this.node.width / 2, y - this.node.height / 2, 0);
                this._attackDot.setPosition(0, 0, 0);
                this._attackMovementTouch = touch;
            }
        }
    }

    OnAttackTouchMove(event: cc.Event.EventTouch) {
        let touches = event.getTouches();

        for (let i = 0; i < touches.length; ++i) {
            let touch = touches[i];
            if (this._attackMovementTouch && touch.getID() == this._attackMovementTouch.getID()) {
                let x = touch.getLocationX();
                let y = touch.getLocationY();

                let pos = this._attack.position;
                let ox = x - this.node.width / 2 - pos.x;
                let oy = y - this.node.height / 2 - pos.y;

                let len = Math.sqrt(ox * ox + oy * oy);
                if (len <= 0) {
                    return;
                }

                let dirX = ox / len;
                let dirY = oy / len;
                let radius = this._attack.width / 2;
                if (len > radius) {
                    len = radius;
                    ox = dirX * radius;
                    oy = dirY * radius;
                }

                this._attackDot.setPosition(ox, oy, 0);
                EventManager.Scene.emit(MyEvent.SET_ATTACK_DIR, cc.v2(dirX, dirY));
            }
        }
    }

    OnAttackTouchEnd(event: cc.Event.EventTouch) {
        let touches = event.getTouches();
        EventManager.Scene.emit(MyEvent.Stop_Fire);

        for (let i = 0; i < touches.length; ++i) {
            let touch = touches[i];
            if (this._attackMovementTouch && touch.getID() == this._attackMovementTouch.getID()) {
                this._attackMovementTouch = null;
                this._attackDot.setPosition(cc.Vec3.ZERO);
            }
        }
    }

    //#region 键盘控制

    private _keys = [];
    private _dir: cc.Vec2 = new cc.Vec2(0, 0);

    onKeyDown(event) {
        let keyCode = event.keyCode;
        if (keyCode == cc.macro.KEY.a || keyCode == cc.macro.KEY.s || keyCode == cc.macro.KEY.d || keyCode == cc.macro.KEY.w) {
            if (this._keys.indexOf(keyCode) == -1) {
                this._keys.push(keyCode);
                this.updateDirection();
            }
        }

        if (keyCode == keyCode.SPACE) {
            // EventManager.Scene.emit(MyEvent.JUMP);
        }
    }

    onKeyUp(event) {
        let keyCode = event.keyCode;
        if (keyCode == cc.macro.KEY.a || keyCode == cc.macro.KEY.s || keyCode == cc.macro.KEY.d || keyCode == cc.macro.KEY.w) {
            let index = this._keys.indexOf(keyCode);
            if (index != -1) {
                this._keys.splice(index, 1);
                switch (keyCode) {
                    case cc.macro.KEY.a:
                    case cc.macro.KEY.d: this._dir.x = 0; break;
                    case cc.macro.KEY.w:
                    case cc.macro.KEY.s: this._dir.y = 0; break;
                }
                this.updateDirection();
            }
        }
    }

    updateDirection() {
        if (this._keys.some(e => e == cc.macro.KEY.a)) this._dir.x = -1;
        if (this._keys.some(e => e == cc.macro.KEY.d)) this._dir.x = 1;
        if (this._keys.some(e => e == cc.macro.KEY.w)) this._dir.y = 1;
        if (this._keys.some(e => e == cc.macro.KEY.s)) this._dir.y = -1;

        EventManager.Scene.emit(MyEvent.MOVEMENT, this._dir.x, this._dir.y, 1.0);
    }

    //#endregion

}